/* Copyright (c) 2009 SpringShowcase, Inc.
 * All right reserved.
 * http://code.google.com/p/springshowcase/
 * This software is the confidential and proprietary information of BeyondWeb
 * , Inc. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license agreement
 * you entered into with BeyondWeb.
 *
 * Revision History
 * Author              Date             Description
 * ------------------   --------------    ------------------
 *  taeki.kim           2010. 3. 31.        
*/
package org.springshowcase.core.commons.config;

import java.net.URL;

import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationConverter;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;


// TODO: Auto-generated Javadoc
/* Copyright (c) beyondj2ee, Inc.
 * All right reserved.
 *
 * This software is the confidential and proprietary information of SK Telecom
 * , Inc. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license agreement
 * you entered into with SKTelecom.
 *
 * Revision History
 * Author              Date             Description
 * ------------------   --------------    ------------------
 * kim.tae.ki           2010.03.22                               
 */


/**
 * The Class CommonsConfigurationFactoryBean.
 */
public class CommonsConfigurationFactoryBean implements InitializingBean, FactoryBean {
	// ---------------------------------------------------------------------
	// Class Variable Declaration
	// ---------------------------------------------------------------------
	/** The Constant logger. */
	private static final Logger logger = LoggerFactory
			.getLogger(CommonsConfigurationFactoryBean.class);
	
	/** The configuration. */
	private CompositeConfiguration configuration;

	/** The configurations. */
	private Configuration[] configurations;

	/** The locations. */
	private Resource[] locations;

	/** The throw exception on missing. */
	private boolean throwExceptionOnMissing = true;

	// ---------------------------------------------------------------------
	// Constructor Method Declaration
	// ---------------------------------------------------------------------
	/**
	 * Instantiates a new commons configuration factory bean.
	 */
	public CommonsConfigurationFactoryBean() {
	}
	// ---------------------------------------------------------------------
	// DI Method (setter,getter) Declaration
	// ---------------------------------------------------------------------
	// ---------------------------------------------------------------------
	// this Method (public/private) Declaration
	// ---------------------------------------------------------------------
	/**
	 * Instantiates a new commons configuration factory bean.
	 * 
	 * @param configuration the configuration
	 */
	public CommonsConfigurationFactoryBean(Configuration configuration) {
		Assert.notNull(configuration);
		this.configuration = new CompositeConfiguration(configuration);
	}

	/**
	 * Gets the object.
	 * 
	 * @return the object
	 * 
	 * @throws Exception the exception
	 * 
	 * @see org.springframework.beans.factory.FactoryBean#getObject()
	 */
	public Object getObject() throws Exception {
		return (configuration != null) ? ConfigurationConverter.getProperties(configuration) : null;
	}

	/**
	 * Gets the object type.
	 * 
	 * @return the object type
	 * 
	 * @see org.springframework.beans.factory.FactoryBean#getObjectType()
	 */
	public Class getObjectType() {
		return java.util.Properties.class;
	}

	/**
	 * Checks if is singleton.
	 * 
	 * @return true, if checks if is singleton
	 * 
	 * @see org.springframework.beans.factory.FactoryBean#isSingleton()
	 */
	public boolean isSingleton() {
		return true;
	}

	/**
	 * Gets the configurations.
	 * 
	 * @return Returns the configurations.
	 */
	public Configuration[] getConfigurations() {
		return configurations;
	}

	/**
	 * Set the commons configurations objects which will be used as properties.
	 * 
	 * @param configurations the configurations
	 */
	public void setConfigurations(Configuration[] configurations) {
		this.configurations = configurations;
	}

	/**
	 * Gets the locations.
	 * 
	 * @return the locations
	 */
	public Resource[] getLocations() {
		return locations;
	}

	/**
	 * Shortcut for loading configuration from Spring resources. It will
	 * internally create a PropertiesConfiguration object based on the URL
	 * retrieved from the given Resources.
	 * 
	 * @param locations the locations
	 */
	public void setLocations(Resource[] locations) {
		this.locations = locations;
	}

	/**
	 * Checks if is throw exception on missing.
	 * 
	 * @return true, if is throw exception on missing
	 */
	public boolean isThrowExceptionOnMissing() {
		return throwExceptionOnMissing;
	}

	/**
	 * Set the underlying Commons CompositeConfiguration throwExceptionOnMissing
	 * flag.
	 * 
	 * @param throwExceptionOnMissing the throw exception on missing
	 */
	public void setThrowExceptionOnMissing(boolean throwExceptionOnMissing) {
		this.throwExceptionOnMissing = throwExceptionOnMissing;
	}

	/**
	 * Getter for the underlying CompositeConfiguration object.
	 * 
	 * @return the configuration
	 */
	public CompositeConfiguration getConfiguration() {
		return configuration;
	}
	// ---------------------------------------------------------------------
	// interface implement Method (public/private) Declaration
	// ---------------------------------------------------------------------
	/**
	 * After properties set.
	 * 
	 * @throws Exception the exception
	 * 
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	public void afterPropertiesSet() throws Exception {
		
		logger.info("config Initialize....");
		
		if (configuration == null && (configurations == null || configurations.length == 0)
				&& (locations == null || locations.length == 0))
			throw new IllegalArgumentException("no configuration object or location specified");

		if (configuration == null)
			configuration = new CompositeConfiguration();

		configuration.setThrowExceptionOnMissing(throwExceptionOnMissing);

		if (configurations != null) {
			for (int i = 0; i < configurations.length; i++) {
				configuration.addConfiguration(configurations[i]);
			}
		}
		
		if (locations != null) {
			for (int i = 0; i < locations.length; i++) {
				URL url = locations[i].getURL();
				Configuration props = new PropertiesConfiguration(url);
				configuration.addConfiguration(props);
			}
		}
	}
	// ---------------------------------------------------------------------
	// abstract implement Method (public/private) Declaration
	// ---------------------------------------------------------------------
	// ---------------------------------------------------------------------
	// abstract Method (public/private) Declaration
	// ---------------------------------------------------------------------
}
